﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TimeCalc
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var dateTimes = GetAutoStartTimes(5, -1, 5);


            startText.ContextMenu = new ContextMenu(); ;
            startText.ContextMenu.Popup += new EventHandler(startTextContextMenu_Popup);


            classReceivesText.ContextMenu = new ContextMenu();
            classReceivesText.ContextMenu.Popup += new EventHandler(classRecievesTextContextMenu_Popup);


            extraTimeText.ContextMenu = new ContextMenu();
            extraTimeText.ContextMenu.Popup += new EventHandler(extraTimeTextContextMenu_Popup);
        }

        #region Start Time Context

        void startTextContextMenu_Popup(object sender, EventArgs e)
        {
            ContextMenu contextMenu = sender as ContextMenu;
            contextMenu.MenuItems.Clear();

            var dateTimes = GetAutoStartTimes(5, -1, 5);

            foreach (DateTime dt in dateTimes)
            {
                MenuItem menuItem = new MenuItem(dt.ToShortTimeString(), new EventHandler(autoStartTime_ClickHandler));
                contextMenu.MenuItems.Add(menuItem);
            }
        }

        private void autoStartTime_ClickHandler(object source, EventArgs e)
        {
            MenuItem menuItem = source as MenuItem;
            startText.Text = menuItem.Text;
        }

        List<DateTime> GetAutoStartTimes(int increment, int incrementOffset, int incrementCount)
        {
            int mins = DateTime.Now.Minute;
            int fives = mins / 5 + incrementOffset + 1;

            DateTime baseDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
                                                DateTime.Now.Hour, fives * 5, 0);

            List<DateTime> dateTimes = new List<DateTime>(10);
            for (int i = 0; i < incrementCount; ++i)
            {
                dateTimes.Add(baseDateTime);
                baseDateTime = baseDateTime + new TimeSpan(0, 5, 0);
            }

            return dateTimes;
        }

        #endregion

        #region Class Receives Context

        class ValueDescriptionPair
        {
            public string Value;
            public string Description;

            public ValueDescriptionPair(string value, string description)
            {
                Value = value;
                Description = description;
            }

            public override string ToString()
            {
                string formatString = "{0} - {1}";
                return string.Format(formatString, Value, Description);
            }
        }

        List<ValueDescriptionPair> autoClassRecieves;

        void classRecievesTextContextMenu_Popup(object sender, EventArgs e)
        {
            if (autoClassRecieves != null)
                return; // list already setup

           
            autoClassRecieves = GetAutoClassRecieves();

            ContextMenu contextMenu = sender as ContextMenu;
            foreach (ValueDescriptionPair timeFactor in autoClassRecieves)
            {
                MenuItem menuItem = new MenuItem(timeFactor.ToString(), new EventHandler(autoClassRecieves_ClickHandler));
                menuItem.Tag = timeFactor;
                contextMenu.MenuItems.Add(menuItem);
            }

        }

        private void autoClassRecieves_ClickHandler(object source, EventArgs e)
        {
            MenuItem menuItem = source as MenuItem;
            ValueDescriptionPair timeFactor = menuItem.Tag as ValueDescriptionPair;
            classReceivesText.Text = timeFactor.Value;
        }

        List<ValueDescriptionPair> GetAutoClassRecieves()
        {
            var timeFactors = new List<ValueDescriptionPair>(5);

            timeFactors.Add(new ValueDescriptionPair("0:15", "15 Minutes"));
            timeFactors.Add(new ValueDescriptionPair("0:30", "30 Minutes"));
            timeFactors.Add(new ValueDescriptionPair("0:50", "50 Minutes"));
            timeFactors.Add(new ValueDescriptionPair("1:00", "1 Hour"));
            timeFactors.Add(new ValueDescriptionPair("1:50", "1 Hour, 50 Minnuts"));
            timeFactors.Add(new ValueDescriptionPair("2:00", "2 Hours"));
            
            return timeFactors;
        }

        #endregion


        #region Extra Time

        List<ValueDescriptionPair> autoExtraTime;

        void extraTimeTextContextMenu_Popup(object sender, EventArgs e)
        {
            if (autoExtraTime != null)
                return; // list already setup


            autoExtraTime = GetAutoExtraTime();

            ContextMenu contextMenu = sender as ContextMenu;
            foreach (ValueDescriptionPair timeFactor in autoExtraTime)
            {
                MenuItem menuItem = new MenuItem(timeFactor.ToString(), new EventHandler(autoExtraTime_ClickHandler));
                menuItem.Tag = timeFactor;
                contextMenu.MenuItems.Add(menuItem);
            }

        }

        private void autoExtraTime_ClickHandler(object source, EventArgs e)
        {
            MenuItem menuItem = source as MenuItem;
            ValueDescriptionPair timeFactor = menuItem.Tag as ValueDescriptionPair;
            extraTimeText.Text = timeFactor.Value;
        }

        List<ValueDescriptionPair> GetAutoExtraTime()
        {
            var timeFactors = new List<ValueDescriptionPair>(5);

            timeFactors.Add(new ValueDescriptionPair("1.0", ""));
            timeFactors.Add(new ValueDescriptionPair("1.5", "One and one-half time"));
            timeFactors.Add(new ValueDescriptionPair("2.0", "Double time"));

            return timeFactors;
        }

        #endregion




        DateTime? start;
        private void startText_TextChanged(object sender, EventArgs e)
        {
            DateTime dateTime;
            if (DateTime.TryParse(startText.Text, out dateTime))
            {
                start = dateTime;
            }
            else
            {
                start = null;
            }
            printTime();
        }

        TimeSpan? classReceives;
        private void classReceivesText_TextChanged(object sender, EventArgs e)
        {
            TimeSpan timeSpan;
            if (TimeSpan.TryParse(classReceivesText.Text, out timeSpan))
            {
                classReceives = timeSpan;
            }
            else
            {
                classReceives = null;
            }
            printTime();
        }

        double? accommodation;
        private void extraTimeText_TextChanged(object sender, EventArgs e)
        {
            double value;
            if (double.TryParse(extraTimeText.Text, out value))
            {
                accommodation = value;
            }
            else
            {
                accommodation = null;
            }
            printTime();
        }

        private void printTime() {


            //errorProvider1.Clear();
            //if (start == null && startText.Text.Trim().Length > 0) errorProvider1.SetError(labelStart, "Time should be formatted as hh:mm");
            //if (classReceives == null && classReceivesText.Text.Trim().Length > 0) errorProvider1.SetError(labelClassReceives, "Time should be formatted as hh:mm");
            //if (accommodation == null && extraTimeText.Text.Trim().Length > 0) errorProvider1.SetError(labelExtraTime, "Extra time should be formatted as a scaling factor, e.g.: '2.0' for double time");

            if (start == null || classReceives == null || accommodation == null)
            {
                endText.Text = "";
                studentReceivesText.Text = "";
                return;
            }

            ExamTime extraTime = new ExamTime(start.Value, classReceives.Value, accommodation.Value);

            studentReceivesText.Text = extraTime.StudentReceives.Hours.ToString() + ":" + extraTime.StudentReceives.Minutes.ToString();
            if (extraTime.StudentReceives.Seconds != 0)
                studentReceivesText.Text += ":" + extraTime.StudentReceives.Seconds.ToString();

            endText.Text = extraTime.End.ToShortTimeString();
            if (extraTime.End.Second != 0)
                endText.Text = extraTime.End.ToLongTimeString();

            Console.WriteLine(extraTime);


        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void aboutExtraTimeCalculatorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Extra Time Calculator\n\nMark Samuelson\nmarksam@gmail.com");
        }

        
    }


    public class ExamTime
    {
        DateTime _start;
        TimeSpan _classReceives;
        double _accommodation;
        TimeSpan _studentReceives;
        DateTime _end;

        public TimeSpan StudentReceives { get { return _studentReceives; } }
        public DateTime End { get { return _end; } }

        public ExamTime(DateTime start, TimeSpan classReceives, double accommodation)
        {
            _start = start;
            _classReceives = classReceives;
            _accommodation = accommodation;


            _studentReceives = new TimeSpan(0, 0, 0, (int)(_classReceives.TotalSeconds * accommodation));
            _end = _start + _studentReceives;
        }



        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("Class Receives:   "); sb.AppendLine(_classReceives.ToString());
            sb.Append("Accomidation:     "); sb.AppendLine(_accommodation.ToString());
            sb.Append("Student Receives: "); sb.AppendLine(_studentReceives.ToString());

            sb.Append("Start: "); sb.AppendLine(_start.ToString());
            sb.Append("End:   "); sb.AppendLine(_end.ToString());

            return sb.ToString();
        }

    }
}
